﻿namespace BM.Tools.WebControls.MForm.Design
{    
    using System.ComponentModel.Design;
    using System.Diagnostics.CodeAnalysis;        
    using System.Web.UI;
    using System.Windows.Forms;
    using System.Xml;

    using BM.Tools.WebControls.MForm.Controls;
    using BM.Tools.WebControls.MForm.Design.PropertiesGeneration;
    using BM.Tools.WebControls.MForm.Generator;

    /// <summary>
    /// This is a <see cref="DesignerActionList" /> of the <see cref="Root"/> control.
    /// </summary>
    internal class RootActionList : OffspringsOwnerActionList
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="RootActionList"/> class. 
        /// </summary>
        /// <param name="designer">
        /// The designer.
        /// </param>
        /// <param name="offspring">
        /// The offspring.
        /// </param>
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        public RootActionList(RootDesigner designer, OffspringsOwner offspring)
            : base(designer, offspring)
        {
        }

        /// <summary>
        /// Gets or sets the designer mode.
        /// </summary>
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        public FormBuilderMode DesignerMode
        {
            get
            {
                return RootDesigner.DesignerMode;
            }

            set
            {
                if (value != RootDesigner.DesignerMode)
                {
                    RootDesigner.DesignerMode = value;
                    RootDesigner.UpdateDesignTimeHtml();
                }
            }
        }

        /// <summary>
        /// Gets the Root control.
        /// </summary>
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        public Root Root
        {
            get
            {
                return Offspring as Root;
            }
        }

        /// <summary>
        /// Gets the designer of the Root control.
        /// </summary>
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        private RootDesigner RootDesigner
        {
            get
            {
                return Designer as RootDesigner;
            }
        }

        /// <summary>
        /// Clears the contents of the root control.
        /// </summary>
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        public void ClearContent()
        {
            RootDesigner.ResetTemplate(Root, "Contents");
        }

        /// <summary>
        /// Gets the action items of the root control.
        /// </summary>
        /// <returns>
        /// The action items.
        /// </returns>
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        public override DesignerActionItemCollection GetSortedActionItems()
        {
            DesignerActionItemCollection items = base.GetSortedActionItems();

            items.Insert(0, new DesignerActionHeaderItem("Designer"));
            items.Insert(1, new DesignerActionPropertyItem("DesignerMode", "designer mode", "Designer", string.Empty));

            if (Editable)
            {
                items.Add(new DesignerActionHeaderItem("Contents"));
                items.Add(
                        new DesignerActionMethodItem(
                                this,
                                "LoadFromDataDefinition",
                                "load a root template from data definition",
                                "Contents",
                                "creates a template based on the chosen element in the xsd/wsdl file or based on the class definition in a dll file.",
                                true));
                items.Add(
                        new DesignerActionMethodItem(
                                this,
                                "GeneratePropertiesForSingleInstanceTemplates",
                                "Generate properties for single instance templates",
                                "Contents",
                                "creates properties for those offspring items that may appear only once",
                                true));
                items.Add(
                        new DesignerActionMethodItem(
                                this,
                                "ClearContent",
                                "clear the content of the root",
                                "Contents",
                                "removes everything from the content of the root",
                                true));
            }

            return items;
        }

        /// <summary>
        /// Opens a winform that allows defining the names of the properties that could be generated from the root control.
        /// In case of dialog result OK, the generation is performed using the <see cref="PropertiesGenerator" /> class.
        /// </summary>
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        public void GeneratePropertiesForSingleInstanceTemplates()
        {                        
            var form = new PropertiesForm(Root, (EnvDTE.ProjectItem)Component.Site.GetService(typeof(EnvDTE.ProjectItem)));
            form.ShowDialog();
        }

        /// <summary>
        /// Opens a winform that allows generation of the form according to a data definition provided (a schema, wsdl or managed library).
        /// In case of dialog result OK, the Contents template in the Root control is filled in.
        /// </summary>     
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        public void LoadFromDataDefinition()
        {
            var form = new GeneratorForm();
            if (form.ShowDialog() == DialogResult.OK)
            {
                GenerateRootContentsAndUriMappings(form);
                GeneratePropertiesForSingleInstanceTemplates();
            }
        }

        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This code is invoked internally by the designer")]
        private void GenerateRootContentsAndUriMappings(GeneratorForm form)
        {
            Root.IsDuringGeneration = true;
            RootDesigner.ResetTemplate(Root, "Contents");

            Pair data = form.GetGeneratedData();
            SetProperty("Contents", data.First);
            RootDesigner.DesignerMode = FormBuilderMode.View;
            SetProperty("Contents", data.First);
            Root.UriMappings.Clear();
            foreach (var mapping in UriMappings.FromManager(data.Second as XmlNamespaceManager))
            {
                Root.UriMappings.Add(mapping);
            }    
        
            RootDesigner.UpdateDesignTimeHtml();
        }
    }
}